Micron Document
NexusPi Git Node


Displaying Raw • Download

native/PinMap.cpp HEAD (592c826d) Text, 10.35 KB

T8b949e// Copyright (C) 2026, Chad Attermann
T8b949e//
T8b949e// Definitions for the runtime-configurable pin globals declared as
T8b949e// `extern int pin_*` in Boards.h under MCU_VARIANT == MCU_NATIVE.
T8b949e// Populated from native_config::g_config before LoRa->begin() runs.

Tff7b72#Tff7b72include T8b949e"config.h"
Tff7b72#Tff7b72include T8b949e"PinMap.h"
Tff7b72#Tff7b72include T8b949e"EEPROMShim.h"
Tff7b72#Tff7b72include T8b949e"../Boards.h"T8b949e // PRODUCT_NATIVE_LINUX / MODEL_60 / BOARD_NATIVE_LINUX constants
Tff7b72#Tff7b72include T8b949e"../ROM.h"T8b949e // CONF_OK_BYTE, INFO_LOCK_BYTE, ADDR_* offsets
Tff7b72#Tff7b72include T8b949e<Arduino.h>T8b949e // pinMode / digitalWrite / HIGH / LOW / OUTPUT
Tff7b72#Tff7b72include T8b949e<cstdio>
Tff7b72#Tff7b72include T8b949e<vector>

Tff7b72#Tff7b72ifdef PORTDUINO_LINUX_HARDWARE
Tff7b72#Tff7b72include T8b949e<PortduinoGPIO.h>
Tff7b72#Tff7b72include T8b949e<linux/gpio/LinuxGPIOPin.h>
Tff7b72#Tff7b72include T8b949e<gpiod.h>
Tff7b72#Tff7b72include T8b949e<string>
Tff7b72#Tff7b72endif

T8b949e// --- Pin globals (single definition) ---
Tffa657int Te6edf3pin_cs Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_reset Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_dio Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_busy Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_rxen Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_txen Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_led_rx Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_led_tx Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_tcxo_enable Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_sclk Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_mosi Tff7b72= T79c0ff-1Tb4b4b4;
Tffa657int Te6edf3pin_miso Tff7b72= T79c0ff-1Tb4b4b4;

T8b949e// --- EEPROM shim instance (single definition) ---
Te6edf3EEPROMClass Te6edf3EEPROMTb4b4b4;

Tff7b72namespace T7ee787native_pinmap Tb4b4b4{

T8b949e// Copy pin numbers from the loaded config into the globals the modem
T8b949e// drivers consult via LoRa->setPins(). Call once after native_config::load()
T8b949e// and before setup().
Tffa657void Td2a8ffapplyTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72const Tff7b72autoTff7b72& Te6edf3c Tff7b72= Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4;
Te6edf3pin_cs Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_csTb4b4b4;
Te6edf3pin_reset Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_resetTb4b4b4;
Te6edf3pin_dio Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_dioTb4b4b4;
Te6edf3pin_busy Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_busyTb4b4b4;
Te6edf3pin_rxen Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_rxenTb4b4b4;
Te6edf3pin_txen Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_txenTb4b4b4;
Te6edf3pin_led_rx Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_led_rxTb4b4b4;
Te6edf3pin_led_tx Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_led_txTb4b4b4;
Te6edf3pin_tcxo_enable Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_tcxo_enableTb4b4b4;
Te6edf3pin_sclk Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_sclkTb4b4b4;
Te6edf3pin_mosi Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_mosiTb4b4b4;
Te6edf3pin_miso Tff7b72= Te6edf3cTb4b4b4.Te6edf3pin_misoTb4b4b4;
Tb4b4b4}

T8b949e// Bind Portduino's logical pin numbers to real libgpiod-backed lines.
T8b949e// Identity-mapping: the value of `pin_*` in rnoded.conf is treated
T8b949e// as both the Portduino logical pin number AND the gpiochip line offset
T8b949e// (BCM number on a Raspberry Pi). No-op on macOS / cross_platform — the
T8b949e// `#ifdef PORTDUINO_LINUX_HARDWARE` body is empty there.
T8b949e//
T8b949e// Excludes the SPI bus pins (CS, SCLK, MOSI, MISO). Those lines are owned
T8b949e// by the `spidev` kernel driver via the Pi's device tree; requesting them
T8b949e// through libgpiod from userspace would conflict.
Tffa657void Td2a8ffbind_linux_gpiosTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef PORTDUINO_LINUX_HARDWARE
T8b949e// Portduino's LinuxGPIOPin::getLine() (LinuxGPIOPin.cpp:225-249)
T8b949e// iterates /dev/gpiochip* and matches by gpiod_chip_label() — the
T8b949e// SoC-specific identifier (e.g. "pinctrl-bcm2711" on a Pi, "gpio1"
T8b949e// on Rockchip), NOT the device filename. So we can't just strip
T8b949e// "/dev/" off the user's gpio_chip path and pass that as the label.
T8b949e// Open the chip ourselves to resolve its real label, then hand that
T8b949e// to LinuxGPIOPin.
Tff7b72const Tffa657charTff7b72* Te6edf3chipPath Tff7b72= Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3gpio_chipTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72struct T56d364gpiod_chipTff7b72* Te6edf3probe Tff7b72= Te6edf3gpiod_chip_openTb4b4b4(Te6edf3chipPathTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3probeTb4b4b4) Tb4b4b4{
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4,
Ta5d6ff"Ta5d6ff[pinmap] could not open %s: %s — GPIO binding skippedTffea00\nTa5d6ff"Tb4b4b4,
Te6edf3chipPathTb4b4b4, Te6edf3stdTff7b72:Tff7b72:Te6edf3strerrorTb4b4b4(Te6edf3errnoTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72returnTb4b4b4;
Tb4b4b4}
Tff7b72const Te6edf3stdTff7b72:Tff7b72:Te6edf3string Te6edf3chipLabel Tff7b72= Te6edf3gpiod_chip_labelTb4b4b4(Te6edf3probeTb4b4b4)Tb4b4b4;
Te6edf3gpiod_chip_closeTb4b4b4(Te6edf3probeTb4b4b4)Tb4b4b4;

T8b949e// Pattern adopted from meshtasticd (PortduinoGlue.cpp::initGPIOPin):
T8b949e// construct the pin, mark it silent BEFORE binding, then hand to
T8b949e// gpioBind. Portduino's base GPIOPin::writePin/refreshState/setPinMode
T8b949e// all log unconditionally via the unfiltered Portduino log(); the only
T8b949e// way to quiet them is the per-pin silent flag. Once silenced, normal
T8b949e// SPI activity (CS toggles) and Portduino's ISR-poll thread no longer
T8b949e// drown the output — the modem driver's own Serial logs come through.
T8b949e//
T8b949e// SCLK / MOSI / MISO are always claimed by the spidev driver via the
T8b949e// pinctrl device tree node, so we never bind those.
T8b949e//
T8b949e// CS gets a silent SimGPIOPin rather than a LinuxGPIOPin: spidev owns
T8b949e// the SPI controller's hardware CS automatically across each
T8b949e// SPI_IOC_MESSAGE ioctl, so the modem driver's digitalWrite(_ss, ...)
T8b949e// is intentionally a no-op at the OS level. Binding a SimGPIOPin (vs.
T8b949e// letting it default to "Unbound") just lets us flip its silent flag.
Tff7b72auto Te6edf3bind_linux Tff7b72= Tb4b4b4[Tff7b72&Tb4b4b4]Tb4b4b4(Tffa657int Te6edf3pinTb4b4b4, Tff7b72const Tffa657charTff7b72* Te6edf3nameTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3pin Tff7b72< T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4; T8b949e// -1 = disabled in config
Tff7b72try Tb4b4b4{
Te6edf3GPIOPinTff7b72* Te6edf3p Tff7b72= Tff7b72new Te6edf3LinuxGPIOPinTb4b4b4(Te6edf3pinTb4b4b4, Te6edf3chipLabelTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3pinTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4;
Te6edf3pTff7b72-Tff7b72>Te6edf3setSilentTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3gpioBindTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4(Tff7b72const Te6edf3stdTff7b72:Tff7b72:Te6edf3exceptionTff7b72& Te6edf3eTb4b4b4) Tb4b4b4{
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4,
Ta5d6ff"Ta5d6ff[pinmap] %s (line %d on %s) NOT bound: %s — leaving as Ta5d6ff"
Ta5d6ff"Ta5d6ffPortduino sim (typically because another driver owns the line)Tffea00\nTa5d6ff"Tb4b4b4,
Te6edf3nameTb4b4b4, Te6edf3pinTb4b4b4, Te6edf3chipLabelTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3eTb4b4b4.Te6edf3whatTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4;
Tff7b72auto Te6edf3bind_sim_silent Tff7b72= Tb4b4b4[Tff7b72&Tb4b4b4]Tb4b4b4(Tffa657int Te6edf3pinTb4b4b4, Tff7b72const Tffa657charTff7b72* Te6edf3nameTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3pin Tff7b72< T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3GPIOPinTff7b72* Te6edf3p Tff7b72= Tff7b72new Te6edf3SimGPIOPinTb4b4b4(Te6edf3pinTb4b4b4, Te6edf3nameTb4b4b4)Tb4b4b4;
Te6edf3pTff7b72-Tff7b72>Te6edf3setSilentTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3gpioBindTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;

Tff7b72const Tff7b72autoTff7b72& Te6edf3c Tff7b72= Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4;
Te6edf3bind_sim_silentTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_csTb4b4b4, Ta5d6ff"Ta5d6ffCSTa5d6ff"Tb4b4b4)Tb4b4b4; T8b949e// spidev owns the real CS
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_resetTb4b4b4, Ta5d6ff"Ta5d6ffRESETTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_busyTb4b4b4, Ta5d6ff"Ta5d6ffBUSYTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_dioTb4b4b4, Ta5d6ff"Ta5d6ffDIO1Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_rxenTb4b4b4, Ta5d6ff"Ta5d6ffRXENTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_txenTb4b4b4, Ta5d6ff"Ta5d6ffTXENTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_tcxo_enableTb4b4b4,Ta5d6ff"Ta5d6ffTCXO_ENTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_led_rxTb4b4b4, Ta5d6ff"Ta5d6ffLED_RXTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3bind_linuxTb4b4b4(Te6edf3cTb4b4b4.Te6edf3pin_led_txTb4b4b4, Ta5d6ff"Ta5d6ffLED_TXTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Tff7b72autoTff7b72& Te6edf3entry Tff7b72: Te6edf3cTb4b4b4.Te6edf3radio_enable_pinsTb4b4b4) Tb4b4b4{
Te6edf3bind_linuxTb4b4b4(Te6edf3entryTb4b4b4.Te6edf3firstTb4b4b4, Ta5d6ff"Ta5d6ffRADIO_ENTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4, Ta5d6ff"Ta5d6ff[pinmap] bound Linux GPIOs on %s (label=%s)Tffea00\nTa5d6ff"Tb4b4b4,
Te6edf3chipPathTb4b4b4, Te6edf3chipLabelTb4b4b4.Te6edf3c_strTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

T8b949e// Release the libgpiod handles acquired in bind_linux_gpios() so the
T8b949e// re-exec'd process can re-acquire the same lines. Portduino owns each
T8b949e// bound pin via std::unique_ptr<GPIOPinIf> in its `pins` vector
T8b949e// (PortduinoGPIO.cpp:22); gpioBind() destroys the previous occupant. So
T8b949e// rebinding each pin to a fresh SimGPIOPin triggers ~LinuxGPIOPin, which
T8b949e// in turn calls gpiod_line_release(line).
T8b949e//
T8b949e// No-op on macOS / cross_platform: nothing was acquired in the first
T8b949e// place.
Tffa657void Td2a8ffrelease_linux_gpiosTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72#Tff7b72ifdef PORTDUINO_LINUX_HARDWARE
Tff7b72const Tff7b72autoTff7b72& Te6edf3c Tff7b72= Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3vectorTff7b72<Tffa657intTff7b72> Te6edf3pins Tff7b72= Tb4b4b4{
Te6edf3cTb4b4b4.Te6edf3pin_csTb4b4b4, Te6edf3cTb4b4b4.Te6edf3pin_resetTb4b4b4, Te6edf3cTb4b4b4.Te6edf3pin_busyTb4b4b4, Te6edf3cTb4b4b4.Te6edf3pin_dioTb4b4b4,
Te6edf3cTb4b4b4.Te6edf3pin_rxenTb4b4b4, Te6edf3cTb4b4b4.Te6edf3pin_txenTb4b4b4, Te6edf3cTb4b4b4.Te6edf3pin_tcxo_enableTb4b4b4,
Te6edf3cTb4b4b4.Te6edf3pin_led_rxTb4b4b4, Te6edf3cTb4b4b4.Te6edf3pin_led_txTb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72for Tb4b4b4(Tff7b72const Tff7b72autoTff7b72& Te6edf3entry Tff7b72: Te6edf3cTb4b4b4.Te6edf3radio_enable_pinsTb4b4b4) Tb4b4b4{
Te6edf3pinsTb4b4b4.Te6edf3push_backTb4b4b4(Te6edf3entryTb4b4b4.Te6edf3firstTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72for Tb4b4b4(Tffa657int Te6edf3pin Tff7b72: Te6edf3pinsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3pin Tff7b72< T79c0ff0Tb4b4b4) Tff7b72continueTb4b4b4;
Te6edf3GPIOPinTff7b72* Te6edf3p Tff7b72= Tff7b72new Te6edf3SimGPIOPinTb4b4b4(Te6edf3pinTb4b4b4, Ta5d6ff"Ta5d6ffReleasedTa5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3pTff7b72-Tff7b72>Te6edf3setSilentTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3gpioBindTb4b4b4(Te6edf3pTb4b4b4)Tb4b4b4; T8b949e// unique_ptr::reset() destroys prior LinuxGPIOPin
Tb4b4b4}
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4, Ta5d6ff"Ta5d6ff[pinmap] released Linux GPIOsTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72#Tff7b72endif
Tb4b4b4}

T8b949e// Drive each radio_enable_pins entry to its active level. Uses Arduino-API
T8b949e// pinMode/digitalWrite so this works uniformly on macOS (SimGPIOPin) and
T8b949e// Linux (LinuxGPIOPin) — Portduino routes both through the same vtable.
Tffa657void Td2a8ffassert_radio_enable_pinsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Tff7b72autoTff7b72& Te6edf3entry Tff7b72: Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3radio_enable_pinsTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3pin Tff7b72= Te6edf3entryTb4b4b4.Te6edf3firstTb4b4b4;
Tffa657bool Te6edf3active_high Tff7b72= Te6edf3entryTb4b4b4.Te6edf3secondTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pin Tff7b72< T79c0ff0Tb4b4b4) Tff7b72continueTb4b4b4;
Te6edf3pinModeTb4b4b4(Te6edf3pinTb4b4b4, Te6edf3OUTPUTTb4b4b4)Tb4b4b4;
Te6edf3digitalWriteTb4b4b4(Te6edf3pinTb4b4b4, Te6edf3active_high Tff7b72? Te6edf3HIGH Tff7b72: Te6edf3LOWTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

Tffa657void Td2a8ffdeassert_radio_enable_pinsTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72for Tb4b4b4(Tff7b72const Tff7b72autoTff7b72& Te6edf3entry Tff7b72: Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4.Te6edf3radio_enable_pinsTb4b4b4) Tb4b4b4{
Tffa657int Te6edf3pin Tff7b72= Te6edf3entryTb4b4b4.Te6edf3firstTb4b4b4;
Tffa657bool Te6edf3active_high Tff7b72= Te6edf3entryTb4b4b4.Te6edf3secondTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3pin Tff7b72< T79c0ff0Tb4b4b4) Tff7b72continueTb4b4b4;
Te6edf3pinModeTb4b4b4(Te6edf3pinTb4b4b4, Te6edf3OUTPUTTb4b4b4)Tb4b4b4;
Te6edf3digitalWriteTb4b4b4(Te6edf3pinTb4b4b4, Te6edf3active_high Tff7b72? Te6edf3LOW Tff7b72: Te6edf3HIGHTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}

T8b949e// Seed the EEPROM image with the LoRa radio settings from config so the
T8b949e// existing eeprom_conf_load() path in Utilities.h picks them up during
T8b949e// setup(). Only runs if the EEPROM image lacks the CONF_OK_BYTE sentinel
T8b949e// (first boot or after explicit reset).
Tffa657void Td2a8ffseed_eeprom_if_unprovisionedTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// The firmware reads logical addresses via Config.h's
T8b949e// #define eeprom_addr(a) (a + EEPROM_OFFSET)
T8b949e// so we must apply the same translation when writing, or our bytes
T8b949e// land 824 bytes (EEPROM_SIZE - EEPROM_RESERVED) off from where
T8b949e// validate_status() and eeprom_conf_load() look for them. Local
T8b949e// helper avoids repeating the offset on every write.
Tff7b72auto Te6edf3write_at Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4(Tffa657int Te6edf3addrTb4b4b4, Tffa657uint8_t Te6edf3valTb4b4b4) Tb4b4b4{
Te6edf3EEPROMTb4b4b4.Te6edf3writeTb4b4b4(Te6edf3addr Tff7b72+ Te6edf3EEPROM_OFFSETTb4b4b4, Te6edf3valTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72auto Te6edf3read_at Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4(Tffa657int Te6edf3addrTb4b4b4) Tff7b72-Tff7b72> Tffa657uint8_t Tb4b4b4{
Tff7b72return Te6edf3EEPROMTb4b4b4.Te6edf3readTb4b4b4(Te6edf3addr Tff7b72+ Te6edf3EEPROM_OFFSETTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;

Tff7b72if Tb4b4b4(Te6edf3read_atTb4b4b4(Te6edf3ADDR_CONF_OKTb4b4b4) Tff7b72=Tff7b72= Te6edf3CONF_OK_BYTETb4b4b4) Tff7b72returnTb4b4b4;

T8b949e// --- Device-identity provisioning ---
T8b949e// Write enough of the rnodeconf-style provisioning header that
T8b949e// eeprom_lock_set(), eeprom_product_valid(), eeprom_model_valid(),
T8b949e// and eeprom_hwrev_valid() in Utilities.h all return true on native
T8b949e// builds. The MD5 checksum check (eeprom_checksum_valid()) is gated
T8b949e// out via -DDISABLE_FIRMWARE_CHECKSUM in the native PlatformIO envs,
T8b949e// so we deliberately don't compute / write ADDR_CHKSUM here.
Te6edf3write_atTb4b4b4(Te6edf3ADDR_PRODUCTTb4b4b4, Te6edf3PRODUCT_NATIVE_LINUXTb4b4b4)Tb4b4b4; T8b949e// 0x60
Te6edf3write_atTb4b4b4(Te6edf3ADDR_MODELTb4b4b4, Te6edf3MODEL_60Tb4b4b4)Tb4b4b4; T8b949e// 0x60
Te6edf3write_atTb4b4b4(Te6edf3ADDR_HW_REVTb4b4b4, T79c0ff1Tb4b4b4)Tb4b4b4; T8b949e// any non-0x00/0xFF
Te6edf3write_atTb4b4b4(Te6edf3ADDR_INFO_LOCKTb4b4b4, Te6edf3INFO_LOCK_BYTETb4b4b4)Tb4b4b4; T8b949e// 0x73

T8b949e// --- LoRa radio configuration ---
Tff7b72const Tff7b72autoTff7b72& Te6edf3c Tff7b72= Te6edf3native_configTff7b72:Tff7b72:Te6edf3g_configTb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_SFTb4b4b4, Te6edf3cTb4b4b4.Te6edf3lora_sfTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_CRTb4b4b4, Te6edf3cTb4b4b4.Te6edf3lora_crTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_TXPTb4b4b4, Tff7b72static_castTff7b72<Tffa657uint8_tTff7b72>Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_txpTb4b4b4)Tb4b4b4)Tb4b4b4;

Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_FREQ Tff7b72+ T79c0ff0Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_freq_hz Tff7b72>Tff7b72> T79c0ff24Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_FREQ Tff7b72+ T79c0ff1Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_freq_hz Tff7b72>Tff7b72> T79c0ff16Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_FREQ Tff7b72+ T79c0ff2Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_freq_hz Tff7b72>Tff7b72> T79c0ff8Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_FREQ Tff7b72+ T79c0ff3Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_freq_hz Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;

Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_BW Tff7b72+ T79c0ff0Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_bw_hz Tff7b72>Tff7b72> T79c0ff24Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_BW Tff7b72+ T79c0ff1Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_bw_hz Tff7b72>Tff7b72> T79c0ff16Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_BW Tff7b72+ T79c0ff2Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_bw_hz Tff7b72>Tff7b72> T79c0ff8Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;
Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_BW Tff7b72+ T79c0ff3Tb4b4b4, Tb4b4b4(Te6edf3cTb4b4b4.Te6edf3lora_bw_hz Tb4b4b4) Tff7b72& T79c0ff0xFFTb4b4b4)Tb4b4b4;

Te6edf3write_atTb4b4b4(Te6edf3ADDR_CONF_OKTb4b4b4, Te6edf3CONF_OK_BYTETb4b4b4)Tb4b4b4;
Te6edf3EEPROMTb4b4b4.Te6edf3commitTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3stdTff7b72:Tff7b72:Te6edf3fprintfTb4b4b4(Te6edf3stderrTb4b4b4, Ta5d6ff"Ta5d6ff[pinmap] seeded EEPROM image from configTffea00\nTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tb4b4b4} T8b949e// namespace native_pinmap

Served by rngit 1.5.2 - Generated in 0.03s